import { getLastElement } from './util'
import track from './track'

const  timing = () => {
  // performance.timing已不再推荐使用, 用performance.getEntries() 包含如下数组项
  // 第0项: PerformanceNavigationTiming, 通过 performance.getEntries()[0] 获取
  // 第1项 - 第(N-X)项: PerformanceResourceTiming, 各个资源(js css img)加载用时 
  // 例如获取某个js加载用时 通过 performance.getEntriesByName('http://localhost:8080/monitor.js')
  // 第(N-X)项 - 最后一项: PerformancePaintTiming, 各种绘制用时
  // 例如 const FP = performance.getEntriesByName('first-paint')[0]
  // 例如 const FCP = performance.getEntriesByName('first-contentful-paint')[0]

  // 3 监听FMP LCP
  let FMP, LCP
  new PerformanceObserver((entryList, obeserver) => {
    const perfEntries = entryList.getEntries()
    FMP = perfEntries[0]
    obeserver.disconnect()
  }).observe({ entryTypes: ['element'] })
  new PerformanceObserver((entryList, obeserver) => {
    const perfEntries = entryList.getEntries()
    LCP = perfEntries[0]
    obeserver.disconnect()
  }).observe({ entryTypes: ['largest-contentful-paint'] })

  // 2 为了得出FMP LCP, 模拟插入h1
  setTimeout(() => {
    const content = document.getElementsByClassName('content')[0]
    const h1 = document.createElement('h1')
    h1.innerHTML = '我是有意义的内容'
    // 设置elementtiming属性后 这个节点就被认为是FMP
    h1.setAttribute('elementtiming', 'meaningful')
    content.appendChild(h1)
  }, 1000)

  // 必须写到window.onload里面 否则loadEventStart loadEventEnd等对应load事件的时间都为0 导致最后算出来的duration为0
  // 必须setTimeout至少1秒再读取loadEventEnd 否则为0 导致最后算出来的duration为0
  window.onload = () => {
    setTimeout(() => {
      // 1 performance.getEntries()[0]获取各时间
      const {
        connectEnd,
        connectStart,
        decodedBodySize,
        domComplete,
        domContentLoadedEventEnd,
        domContentLoadedEventStart,
        domInteractive,
        domainLookupEnd,
        domainLookupStart,
        duration,
        encodedBodySize,
        entryType,
        fetchStart,
        initiatorType,
        loadEventEnd,
        loadEventStart,
        name,
        nextHopProtocol,
        redirectCount,
        redirectEnd,
        redirectStart,
        requestStart,
        responseEnd,
        responseStart,
        secureConnectionStart,
        startTime,
        transferSize,
        type,
        unloadEventEnd,
        unloadEventStart,
        workerStart
      } = performance.getEntries()[0]
      const log = {
        kind: 'experience',
        type: 'timing',
        connectEnd,
        connectStart,
        decodedBodySize,
        domComplete,
        domContentLoadedEventEnd,
        domContentLoadedEventStart,
        domInteractive,
        domainLookupEnd,
        domainLookupStart,
        duration,
        encodedBodySize,
        entryType,
        fetchStart,
        initiatorType,
        loadEventEnd,
        loadEventStart,
        name,
        nextHopProtocol,
        redirectCount,
        redirectEnd,
        redirectStart,
        requestStart,
        responseEnd,
        responseStart,
        secureConnectionStart,
        startTime,
        transferSize,
        type,
        unloadEventEnd,
        unloadEventStart,
        workerStart,
        // 4 first-paint首次绘制 对应<div class="content" style="width:600px; height: 600px; background-color: gray;"></div> dom最外层部分
        FP: performance.getEntriesByName('first-paint')[0].startTime,
        // first-contentful-paint 首次dom内容绘制 对应div > input 这些dom内容
        FCP: performance.getEntriesByName('first-contentful-paint')[0].startTime,
        // first-meaningful-paint 首次有意义dom绘制 对应1000毫秒后插入的h1
        // h1.setAttribute('elementtiming', 'meaningful') attribute是elementtiming代表有意义dom
        FMP: FMP.startTime,
        // largest-contentful-paint 首次最大dom绘制 对应1000毫秒后插入的h1
        LCP: LCP.startTime,
        // connectTime: connectEnd - connectStart, 
        // ttfbTime: responseStart - requestStart,
        // responesTime: responseEnd - responseStart,
        // parseDomTime: loadEventStart - responseEnd,
        // donContentLoadTime: domContentLoadedEventEnd - domContentLoadedEventStart,
        // timeToInteractive: domInteractive - fetchStart,
        // loadTime: loadEventStart - fetchStart,
      }
      console.log('性能监控', log, performance.getEntries())
      // track.send(log)
      // 1000毫秒后才模拟插入h1, PerformanceObserver obeserver才完成 才有FMP及LCP 所以这里的setTimeout是2000毫秒
    }, 2000)
  }
}

// 5 performance.getEntries()[0] 各时间点含义, 时序图参考https://gitee.com/adomin/blog/raw/master/img/performance.png
// 从前到后依次为
// startTime: 开始导航的时间。值几乎总为0
// unloaStart、unloadEnd：unload事件。
// redirectStart、redirectEnd：重定向时间。如果没有重定向，值都为0。
// fetchStart：开始取缓存时间。本地缓存(强缓存) -> 如果本地缓存过期 -> 协商缓存。
// domainLookupStart、domainLookupEnd：DNS解析。浏览器缓存 -> 本地host缓存 -> DNS缓存 -> DNS解析
// connnectStart、connectEnd、secureConnectEnd：TCP连接。如果使用的https协议用secureConnectStart字段。
// requestStart：构建请求，携带cookie字段信息等。
// responseStart、responseEnd：响应（先接收响应头，再接收响应体）。
// domInteractive、domComplete：对应到document readystatechange事件上的interactive、complete值
// domContentLoadedEventStart、domContentLoadedEventEnd：对应document DOMContentLoaded事件
// loadStart、loadEnd：对应load事件（当页面资源（脚本、样式、图片、音视频、iframe 等）全部加载完成后）

// 6 domInteractive -> domContentLoadedEventStart -> domContentLoadedEventEnd -> domComplete -> loadStart -> loadEnd
// window.addEventListener('load', (event) => {
//   console.log('load')
// });
// document.addEventListener('readystatechange', (event) => {
//   console.log(document.readyState)
// });
// document.addEventListener('DOMContentLoaded', (event) => {
//   console.log('DOMContentLoaded')
// });
// 依次输出 readystate: interactive -> DOMContentLoaded -> readystate: complete -> load

// 7 todo
// 如何统计卡顿
// 阿里云 日志SLS 可视化展示
// 实现报警 设置阈值
// 主流开源 sentry 灯塔 搭配react  vue
// 商业 神策
// 如何性能优化

export default timing